package cn.metona.utils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public final class CollectionUtils {

    // 私有构造函数，防止实例化
    private CollectionUtils() {
        throw new UnsupportedOperationException("Utility class");
    }

    /**
     * 判断集合是否为空
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断集合是否不为空
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 合并多个集合
     */
    @SafeVarargs
    public static <T> List<T> merge(Collection<T>... collections) {
        List<T> mergedList = new ArrayList<>();
        for (Collection<T> collection : collections) {
            if (isNotEmpty(collection)) {
                mergedList.addAll(collection);
            }
        }
        return mergedList;
    }

    /**
     * 过滤集合中的元素
     */
    public static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }
        return collection.stream().filter(predicate).toList();
    }

    /**
     * 将集合转换为字符串
     */
    public static <T> String join(Collection<T> collection, String delimiter) {
        if (isEmpty(collection)) {
            return "";
        }
        return String.join(delimiter, collection.stream().map(Object::toString).toList());
    }

    /**
     * 判断两个集合是否相等（忽略顺序）
     */
    public static boolean equalsIgnoreOrder(Collection<?> collection1, Collection<?> collection2) {
        if (collection1 == null && collection2 == null) {
            return true;
        }
        if (collection1 == null || collection2 == null) {
            return false;
        }
        return collection1.size() == collection2.size() && collection1.containsAll(collection2);
    }

    /**
     * 去重集合中的元素
     */
    public static <T> List<T> distinct(Collection<T> collection) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }
        return collection.stream().distinct().toList();
    }

    /**
     * 对集合进行分组
     */
    public static <T, K> Map<K, List<T>> groupBy(Collection<T> collection, Function<T, K> classifier) {
        if (isEmpty(collection)) {
            return Collections.emptyMap();
        }
        return collection.stream().collect(Collectors.groupingBy(classifier));
    }

    /**
     * 对集合进行排序
     */
    public static <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }
        return collection.stream().sorted(comparator).toList();
    }

    /**
     * 将集合分区（根据条件分为 true 和 false 两部分）
     */
    public static <T> Map<Boolean, List<T>> partition(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return Collections.emptyMap();
        }
        return collection.stream().collect(Collectors.partitioningBy(predicate));
    }

    /**
     * 查找集合中的最大值
     */
    public static <T> T max(Collection<T> collection, Comparator<T> comparator) {
        if (isEmpty(collection)) {
            throw new NoSuchElementException("Collection is empty");
        }
        return collection.stream().max(comparator).orElseThrow();
    }

    /**
     * 查找集合中的最小值
     */
    public static <T> T min(Collection<T> collection, Comparator<T> comparator) {
        if (isEmpty(collection)) {
            throw new NoSuchElementException("Collection is empty");
        }
        return collection.stream().min(comparator).orElseThrow();
    }

    /**
     * 计算集合的交集
     */
    public static <T> List<T> intersection(Collection<T> collection1, Collection<T> collection2) {
        if (isEmpty(collection1) || isEmpty(collection2)) {
            return Collections.emptyList();
        }
        return collection1.stream()
                .filter(collection2::contains)
                .toList();
    }

    /**
     * 计算集合的差集（collection1 - collection2）
     */
    public static <T> List<T> difference(Collection<T> collection1, Collection<T> collection2) {
        if (isEmpty(collection1)) {
            return Collections.emptyList();
        }
        if (isEmpty(collection2)) {
            return new ArrayList<>(collection1);
        }
        return collection1.stream()
                .filter(item -> !collection2.contains(item))
                .toList();
    }

    /**
     * 计算集合的并集
     */
    public static <T> List<T> union(Collection<T> collection1, Collection<T> collection2) {
        List<T> unionList = new ArrayList<>();
        if (isNotEmpty(collection1)) {
            unionList.addAll(collection1);
        }
        if (isNotEmpty(collection2)) {
            unionList.addAll(collection2);
        }
        return distinct(unionList);
    }

    /**
     * 将嵌套集合扁平化
     *
     * @param nestedCollection 嵌套集合
     * @param <T>              集合元素类型
     * @return 扁平化后的集合
     */
    public static <T> List<T> flatten(Collection<? extends Collection<T>> nestedCollection) {
        if (isEmpty(nestedCollection)) {
            return Collections.emptyList();
        }
        return nestedCollection.stream()
                .flatMap(Collection::stream)
                .toList();
    }

    /**
     * 从集合中随机抽取指定数量的元素
     *
     * @param collection 原始集合
     * @param size       抽取数量
     * @param <T>        集合元素类型
     * @return 随机抽取的元素集合
     */
    public static <T> List<T> sample(Collection<T> collection, int size) {
        if (isEmpty(collection) || size <= 0) {
            return Collections.emptyList();
        }
        List<T> list = new ArrayList<>(collection);
        Collections.shuffle(list);
        return list.stream().limit(size).toList();
    }

    /**
     * 对集合进行分页
     *
     * @param collection 原始集合
     * @param page       页码（从 1 开始）
     * @param pageSize   每页大小
     * @param <T>        集合元素类型
     * @return 分页后的集合
     */
    public static <T> List<T> paginate(Collection<T> collection, int page, int pageSize) {
        if (isEmpty(collection) || page <= 0 || pageSize <= 0) {
            return Collections.emptyList();
        }
        int start = (page - 1) * pageSize;
        int end = Math.min(start + pageSize, collection.size());
        if (start >= collection.size()) {
            return Collections.emptyList();
        }
        return new ArrayList<>(collection).subList(start, end);
    }

    /**
     * 将集合转换为另一种类型的集合
     *
     * @param collection 原始集合
     * @param mapper     转换函数
     * @param <T>        原始集合元素类型
     * @param <R>        目标集合元素类型
     * @return 转换后的集合
     */
    public static <T, R> List<R> transform(Collection<T> collection, Function<T, R> mapper) {
        if (isEmpty(collection)) {
            return Collections.emptyList();
        }
        return collection.stream().map(mapper).toList();
    }

    /**
     * 统计集合中每个元素的出现次数
     *
     * @param collection 原始集合
     * @param <T>        集合元素类型
     * @return 元素及其出现次数的 Map
     */
    public static <T> Map<T, Long> countFrequency(Collection<T> collection) {
        if (isEmpty(collection)) {
            return Collections.emptyMap();
        }
        return collection.stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    }

    /**
     * 检查集合中是否包含符合条件的元素
     *
     * @param collection 原始集合
     * @param predicate  条件
     * @param <T>        集合元素类型
     * @return 如果存在符合条件的元素，返回 true；否则返回 false
     */
    public static <T> boolean containsMatch(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return false;
        }
        return collection.stream().anyMatch(predicate);
    }
}
